package com.xiaobaibai.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xiaobaibai.bo.OrderListSelect;
import com.xiaobaibai.common.OrderCommon;
import com.xiaobaibai.common.OrderEnum;
import com.xiaobaibai.entity.*;
import com.xiaobaibai.response.ResponseFormat;
import com.xiaobaibai.service.*;
import com.xiaobaibai.threadPool.MyThreadPoolUnit;
import com.xiaobaibai.units.OrderWXNewsUnit;
import com.xiaobaibai.vo.BargainOrderVo;
import com.xiaobaibai.vo.OrderItemVo;
import com.xiaobaibai.vo.ReturnPayVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@RestController
@Api(tags = "订单管理相关接口")
@RequestMapping("/order")
@Slf4j
@CrossOrigin
public class OrderController {

    @Autowired
    private IOrderService orderService;

    @Autowired
    private IOrderItemService orderItemService;

    @Autowired
    private ICouponService couponService;

    @Autowired
    private IProductService productService;

    @Autowired
    private IBargainUserService bargainUserService;

    @Autowired
    private OrderWXNewsUnit orderWXNewsUnit;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @PostMapping("/list")
    @ApiOperation("订单集合")
    public ResponseFormat getOrderList(@RequestBody OrderListSelect orderListSelect){

        orderListSelect.setPageNum(orderListSelect.getPageNum()-1);
        List<Order> orderList = orderService.getListBySelect(orderListSelect);
        int total=orderService.count();
        Map<String,Object> map=new HashMap<>();
        map.put("data",orderList);
        map.put("total",total);

        return ResponseFormat.ok("获取订单数据成功",map);
    }

    @GetMapping("/detail")
    @ApiOperation("订单详细")
    public ResponseFormat getOrderDetail(@RequestParam(value = "orderId")String orderId) throws ExecutionException, InterruptedException {
        Map<String,Object> map=new HashMap<>();

        CompletableFuture<Void> c1 = CompletableFuture.runAsync(() -> {
            //item的信息不够展示远远不够
            QueryWrapper<OrderItem> q1 = new QueryWrapper<>();
            q1.eq("order_id", orderId);
            List<OrderItem> orderItemList = orderItemService.list(q1);
            for (int i = 0; i < orderItemList.size(); i++) {
                if(orderItemList.get(i).getItemPrice().intValue()==0){
                    orderItemList.remove(i);//移除掉这个砍价商品
                    break;
                }
            }
            Set<Integer> set = orderItemList.stream().map(OrderItem::getProductId).collect(Collectors.toSet());
            //获取商品的集合
            List<Product> productList = productService.getProductByList(set);
            //然后去拼装成vo集合
            List<OrderItemVo> orderItemVoList = new ArrayList<>(productList.size());
            orderItemList.sort(Comparator.comparingInt(OrderItem::getProductId));
            productList.sort(Comparator.comparingInt(Product::getId));
            for (int i = 0; i < productList.size(); i++)
                orderItemVoList.add(OrderItemVo.convertOrderItemVo(productList.get(i), orderItemList.get(i)));
            map.put("itemList", orderItemVoList);
        }, MyThreadPoolUnit.threadPoolExecutor);

        //砍价商品前端遍历出一个0元商品即可
        Order order = orderService.getById(orderId);
        map.put("order",order);
        if (order.getOrderCouponId()!=null){
            //使用了优惠券
            QueryWrapper<Coupon> q2=new QueryWrapper<>();
            q2.select("id","coupon_name","coupon_type","coupon_price","coupon_discount");
            q2.eq("id",order.getOrderCouponId());
            Coupon coupon = couponService.getOne(q2);
            map.put("coupon",coupon);//放入优惠券信息
        }
        if(order.getBargainUserId()!=null){
            QueryWrapper<BargainUser> q3=new QueryWrapper<>();
            q3.select("id","product_id","bargain_progress","create_time");
            q3.eq("id",order.getBargainUserId());
            BargainUser bargainProduct = bargainUserService.getOne(q3);
            QueryWrapper<Product> q4=new QueryWrapper<>();
            q4.select("product_name","product_image","product_price");
            q4.eq("id",bargainProduct.getProductId());
            Product product = productService.getOne(q4);
            BargainOrderVo bargainOrderVo =
                    BargainOrderVo.convertProductAndBargain(product, bargainProduct);
            map.put("bargainProduct",bargainOrderVo);
        }

        CompletableFuture<Void> all = CompletableFuture.allOf(c1);
        all.get();//等待

        return ResponseFormat.ok("获取订单详细信息成功",map);
    }

    @GetMapping("/cancel")
    @ApiOperation("允许取消订单(仅货到付款的订单)")
    public ResponseFormat cancelOrder(@RequestParam(value = "orderId")String orderId){
        QueryWrapper<Order> q1=new QueryWrapper<>();
        q1.select("order_id","order_status","user_phone","user_id","order_coupon_id","bargain_user_id");
        q1.eq("order_id",orderId);
        Order order = orderService.getOne(q1);

        //加锁(与userId)
        Boolean flag = stringRedisTemplate.hasKey(OrderCommon.doOrderLock + order.getUserId());
        if(flag)
            return ResponseFormat.failure("与用户操作冲突,请稍后再试");
        stringRedisTemplate.opsForValue()
                .set(OrderCommon.doOrderLock+order.getUserId(),"1",10, TimeUnit.SECONDS);

        Integer status=order.getOrderStatus();
        if(!status.equals(OrderEnum.CANCELING.getCode()))
            return ResponseFormat.failure("非[取消中]状态");
        //因为仅仅货到付款的订单才会被通知,所以这里无需退款逻辑,只需要去取消订单即可
        try {
            orderService.cancelOrder(order);
        }catch (Exception e){
            log.error(e.getMessage());
            return ResponseFormat.failure(e.getMessage());
        }
        orderWXNewsUnit.sendCancelResult(order.getUserPhone(),orderId,true,null);
        return ResponseFormat.ok("订单取消成功");
    }

    @GetMapping("/refuseCancel")
    @ApiOperation("拒绝取消订单(仅货到付款订单才可以取消)")
    public ResponseFormat refuseCancel(@RequestParam(value = "orderId")String orderId,
                                       @RequestParam(value = "marks")String marks){
        QueryWrapper<Order> q1=new QueryWrapper<>();
        q1.select("order_id","user_phone","order_status","user_id");
        q1.eq("order_id",orderId);
        Order order = orderService.getOne(q1);

        Boolean flag = stringRedisTemplate.hasKey(OrderCommon.doOrderLock + order.getUserId());
        if(flag)
            return ResponseFormat.failure("与用户操作冲突,请稍后再试");
        stringRedisTemplate.opsForValue()
                .set(OrderCommon.doOrderLock+order.getUserId(),"1",10, TimeUnit.SECONDS);

        if(!order.getOrderStatus().equals(OrderEnum.CANCELING.getCode()))
            return ResponseFormat.failure("非[取消中]状态");
        //只有取消中才可以拒绝取消
        order.setOrderStatus(OrderEnum.FACETO.getCode());
        orderService.updateById(order);//改为等待送达,应该改为货到付款
        orderWXNewsUnit.sendCancelResult(order.getUserPhone(),orderId,false,marks);
        return ResponseFormat.ok("已拒绝取消订单");
    }

    @PostMapping("/agreeReturn")
    @ApiOperation("同意退款(已完成或者等待送达)")
    public ResponseFormat agreeReturn(@RequestBody ReturnPayVo returnPayVo){
        String phone=null;
        try {
            phone= orderService.agreeReturn(returnPayVo);//锁在里面
        }catch (Exception e){
            log.error(e.getMessage());
            return ResponseFormat.failure(e.getMessage());
        }
        orderWXNewsUnit.sendAgreeReturn(phone,returnPayVo.getOrderId(),returnPayVo.getAmount());
        return ResponseFormat.ok("系统内部退款逻辑完成,请手动确保微信支付端与此同步");
    }

    @GetMapping("/refuseReturn")
    @ApiOperation("拒绝退款")
    public ResponseFormat refuseReturn(@RequestParam(value = "orderId")String orderId,
                                       @RequestParam(value = "marks")String marks){
        QueryWrapper<Order> q1=new QueryWrapper<>();
        q1.eq("order_id",orderId);
        q1.select("order_id","user_phone","order_status","user_id");
        Order order = orderService.getOne(q1);

        Boolean flag = stringRedisTemplate.hasKey(OrderCommon.doOrderLock + order.getUserId());
        if(flag)
            return ResponseFormat.failure("与用户操作冲突,请稍后再试");
        stringRedisTemplate.opsForValue()
                .set(OrderCommon.doOrderLock+order.getUserId(),"1",10, TimeUnit.SECONDS);

        if(!order.getOrderStatus().equals(OrderEnum.REFUNDING.getCode()))
            return ResponseFormat.failure("非[退款中]状态");
        //去查询订单,是什么订单
        String oldStatus = stringRedisTemplate.opsForValue().get("orderStatus:" + orderId);
        if(oldStatus!=null&&oldStatus.equals("1")){
            //等待送达订单
            order.setOrderStatus(OrderEnum.ING.getCode());
        }else{
            //已完成订单
            order.setOrderStatus(OrderEnum.OK.getCode());
        }
        orderService.updateById(order);//订单改为已完成状态
        orderWXNewsUnit.sendNoReturn(order.getUserPhone(),orderId,marks);
        return ResponseFormat.ok("已拒绝退款",oldStatus==null?2:oldStatus);
    }

}
